<?php
/**
 * @link http://www.tintsoft.com/
 * @copyright Copyright (c) 2013 TintSoft LLC
 * @license http://www.tintsoft.com/license/
 */
namespace Leaps\Base;
use Leaps;

/**
 * PHP错误异常
 *
 * @author Tongle Xu <xutongle@gmail.com>
 * @since 4.0
 */
class ErrorException extends Exception
{
	protected $severity;

	/**
	 * 异常构造方法
	 *
	 * @link http://php.net/manual/en/errorexception.construct.php
	 * @param $message [optional]
	 * @param $code [optional]
	 * @param $severity [optional]
	 * @param $filename [optional]
	 * @param $lineno [optional]
	 * @param $previous [optional]
	 */
	public function __construct($message = '', $code = 0, $severity = 1, $filename = __FILE__, $lineno = __LINE__,\Exception $previous = null)
	{
		parent::__construct ( $message, $code, $previous );
		$this->severity = $severity;
		$this->file = $filename;
		$this->line = $lineno;

		if (function_exists ( 'xdebug_get_function_stack' )) {
			$trace = array_slice ( array_reverse ( xdebug_get_function_stack () ), 3, - 1 );
			foreach ( $trace as &$frame ) {
				if (! isset ( $frame [ 'function' ] )) {
					$frame [ 'function' ] = 'unknown';
				}

				// XDebug < 2.1.1: http://bugs.xdebug.org/view.php?id=695
				if (! isset ( $frame [ 'type' ] ) || $frame [ 'type' ] === 'static') {
					$frame [ 'type' ] = '::';
				} elseif ($frame [ 'type' ] === 'dynamic') {
					$frame [ 'type' ] = '->';
				}

				// XDebug has a different key name
				$frame [ 'args' ] = [ ];
				if (isset ( $frame [ 'params' ] ) && ! isset ( $frame [ 'args' ] )) {
					$frame [ 'args' ] = $frame [ 'params' ];
				}
			}

			$ref = new \ReflectionProperty ( 'Exception', 'trace' );
			$ref->setAccessible ( true );
			$ref->setValue ( $this, $trace );
		}
	}

	/**
	 * 返回严重程度
	 *
	 * @link http://php.net/manual/en/errorexception.getseverity.php
	 * @return int 异常严重级别
	 */
	final public function getSeverity()
	{
		return $this->severity;
	}

	/**
	 * 返回致命错误的类型
	 *
	 * @param array $error 错误从error_get_last()
	 * @return bool 如果错误是致命的类型之一
	 */
	public static function isFatalError($error)
	{
		return isset ( $error [ 'type' ] ) && in_array ( $error [ 'type' ], [
			E_ERROR,
			E_PARSE,
			E_CORE_ERROR,
			E_CORE_WARNING,
			E_COMPILE_ERROR,
			E_COMPILE_WARNING
		] );
	}

	/**
	 * 返回用户友好的异常名称
	 *
	 * @return string
	 */
	public function getName()
	{
		$names = [
			E_ERROR => Leaps::t ( 'leaps', 'Fatal Error' ),
			E_PARSE => Leaps::t ( 'leaps', 'Parse Error' ),
			E_CORE_ERROR => Leaps::t ( 'leaps', 'Core Error' ),
			E_COMPILE_ERROR => Leaps::t ( 'leaps', 'Compile Error' ),
			E_USER_ERROR => Leaps::t ( 'leaps', 'User Error' ),
			E_WARNING => Leaps::t ( 'leaps', 'Warning' ),
			E_CORE_WARNING => Leaps::t ( 'leaps', 'Core Warning' ),
			E_COMPILE_WARNING => Leaps::t ( 'leaps', 'Compile Warning' ),
			E_USER_WARNING => Leaps::t ( 'leaps', 'User Warning' ),
			E_STRICT => Leaps::t ( 'leaps', 'Strict' ),
			E_NOTICE => Leaps::t ( 'leaps', 'Notice' ),
			E_RECOVERABLE_ERROR => Leaps::t ( 'leaps', 'Recoverable Error' ),
			E_DEPRECATED => Leaps::t ( 'leaps', 'Deprecated' )
		];
		return isset ( $names [ $this->getCode () ] ) ? $names [ $this->getCode () ] : Leaps::t ( 'leaps', 'Error' );
	}
}
